﻿
using System;
using System.Collections.Generic;
using System.Linq;

using ComponentBuilder;

using Microsoft.AspNetCore.Components;

namespace BlamanticUI.Components;

/// <summary>
/// Rnder a container of progress that contains a certain number of <see cref="Bar"/> component.
/// </summary>
public class Progress : BlazorParentComponentBase<Progress,Bar>, IHasUIComponent,IHasChildContent, IHasColor, IHasInverted, IHasState, IHasDisabled, IHasAttatched, IHasSize,IHasActive
{

    /// <summary>
    /// A segment of UI content to render.
    /// </summary>
    [Parameter] public RenderFragment? ChildContent { get; set; }
    /// <summary>
    /// Gets or sets the label at below of progress.
    /// </summary>
    [Parameter] public RenderFragment LabelContent { get; set; }
    /// <summary>
    /// The value of a single bar to create automatically. If multiple bars, the value will be ignored.
    /// </summary>
    [Parameter] public double Value { get; set; }
    /// <summary>
    /// The color of a single bar to create automatically. If multiple bars, the value will be ignored.
    /// </summary>
    [Parameter] public Color? Color { get; set; }
    /// <summary>
    /// A Boolean value indicated to show value of percent when a single bar to create automatically. If multiple bars, the value will be ignored.
    /// </summary>
    [Parameter] public bool ShowPercent { get; set; }
    /// <summary>
    /// A Boolean value indicated to show text label at center position when a single bar to create automatically. If multiple bars, the value will be ignored.
    /// </summary>
    [Parameter] public bool Centered { get; set; }
    /// <summary>
    /// Gets or sets the indicating style.
    /// </summary>
    [Parameter] [CssClass("indicating active")] public bool Indicating { get; set; }
    /// <summary>
    /// Gets or sets a value indicating whether adapted inverted background by parent component.
    /// </summary>
    /// <value>
    ///   <c>true</c> if adapted; otherwise, <c>false</c>.
    /// </value>
    [Parameter] public bool Inverted { get; set; }
    /// <summary>
    /// Gets or sets the state.
    /// </summary>
    [Parameter] public State? State { get; set; }
    /// <summary>
    /// Gets or sets a value indicating whether this is disabled.
    /// </summary>
    /// <value>
    ///   <c>true</c> if disabled; otherwise, <c>false</c>.
    /// </value>
    [Parameter] public bool Disabled { get; set; }
    /// <summary>
    /// Gets or sets the speed animation of progress bar.
    /// </summary>
    [Parameter] [CssClass(Order = 19)] public Speed? Speed { get; set; }
    /// <summary>
    /// Gets or sets the animation type.
    /// </summary>
    [Parameter] [CssClass(" indeterminate", Order = 20, Suffix = true)] public AnimationType? Animation { get; set; }
    /// <summary>
    /// Gets or sets the size.
    /// </summary>
    [Parameter] public Size? Size { get; set; }
    /// <summary>
    /// Gets or sets a value indicating whether attach to another.
    /// </summary>
    /// <value>
    ///   <c>true</c> if attached; otherwise, <c>false</c>.
    /// </value>
    [Parameter] public bool Attached { get; set; }
    /// <summary>
    /// Gets or sets the attach position in vertical.
    /// </summary>
    [Parameter] public VerticalPosition? AttachedVertical { get; set; }

    double TotalValue => ChildComponents.Sum(m => (m as Bar).Value);
    /// <summary>
    /// Determined a state of component can be actived.
    /// </summary>
    [Parameter]public bool Active { get; set; }

    /// <summary>
    /// Method invoked when the component has received parameters from its parent in
    /// the render tree, and the incoming values have been assigned to properties.
    /// </summary>
    /// <exception cref="System.ArgumentOutOfRangeException">TotalValue - All value of bars should be in the range of 0-100.</exception>
    protected override void OnParametersSet()
    {
        if (TotalValue < 0 || TotalValue > 100)
        {
            throw new ArgumentOutOfRangeException(nameof(TotalValue), $"All value of bars should be in the range of 0-100.");
        }
    }

    /// <summary>
    /// Appends frames representing an arbitrary fragment of content.
    /// </summary>
    /// <param name="builder"></param>
    /// <param name="sequence"></param>
    protected override void AddContent(RenderTreeBuilder builder, int sequence)
    {
        if (ChildContent is null)
        {
            builder.AddContent(sequence + 1, content =>
            {
                content.CreateComponent<Bar>(10, ChildContent,  attributes: new
                    {
                        Color,
                        Value,
                        ShowPercent,
                        Centered
                    });
            });
        }
        else
        {

            builder.AddContent(sequence + 1, ChildContent);
        }


        builder.CreateElement(sequence + 1, "div", LabelContent, new { @class = "label" }, LabelContent is not null);
    }

    /// <summary>
    /// Overrides to build CSS class by special logical process.
    /// </summary>
    /// <param name="builder">The instance of <see cref="T:ComponentBuilder.Abstrations.ICssClassBuilder" />.</param>
    protected override void BuildCssClass(ICssClassBuilder builder)
    {
        builder.Append("multiple", ChildComponents.Count > 1).Append("progress");
    }
    /// <summary>
    /// Overrides to build additional attributes by special logical process.
    /// </summary>
    /// <param name="attributes">The attributes contains all resolvers to build attributes and <see cref="P:ComponentBuilder.BlazorComponentBase.AdditionalAttributes" />.</param>
    protected override void BuildAttributes(IDictionary<string, object> attributes)
    {
        attributes["data-percent"] = ChildComponents.Sum(m => (m as Bar).Value);
    }

    /// <summary>
    /// Animation type of progress bar.
    /// </summary>
    public enum AnimationType
    {
        /// <summary>
        /// 脉冲模式。
        /// </summary>
        [CssClass("pulsating")]
        Pulsate = 0,
        /// <summary>
        /// 填充模式。
        /// </summary>
        [CssClass("filling")]
        Fill = 1,
        /// <summary>
        /// 幻灯模式。
        /// </summary>
        [CssClass("sliding")]
        Slide,
        /// <summary>
        /// 两翼模式。
        /// </summary>
        [CssClass("swinging")]
        Swing
    }
}
